home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / ksubr.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  12KB  |  449 lines

  1. /* Machine or compiler-dependent portions of kernel
  2.  * Turbo-C version for PC
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  */
  5. #include <stdio.h>
  6. #ifdef MSDOS
  7. #include <dos.h>
  8. #endif
  9. #include "global.h"
  10. #include "config.h"
  11. #include "proc.h"
  12. #ifndef UNIX
  13. #include "pc.h"
  14. #endif
  15. #include "commands.h"
  16. #include "socket.h"
  17.  
  18. #ifndef UNIX
  19. static char *Taskers[] = {
  20.     "",
  21.     "DoubleDos",
  22.     "DesqView",
  23.     "Windows",
  24.     "DOS 5/6",
  25.     "OS/2 DOS",
  26.     "DPMI"
  27. };
  28.  
  29. static oldNull;
  30.  
  31. /* Template for contents of jmp_buf in Turbo C */
  32. struct env {
  33.     unsigned        sp;
  34.     unsigned        ss;
  35.     unsigned        flag;
  36.     unsigned        cs;
  37.     unsigned        ip;
  38.     unsigned        bp;
  39.     unsigned        di;
  40.     unsigned        es;
  41.     unsigned        si;
  42.     unsigned        ds;
  43. };
  44. #endif
  45.  
  46. #ifdef UNIX
  47. /*
  48.  * There are several different ways to implement jmp_buf's.  We use macros to
  49.  * extract the fields.  Note that these must expand into lvalues, because we
  50.  * load them during process initialization.  Current code only uses _SP and
  51.  * _PC; this may change.
  52.  *
  53.  * I should fold the DOS code into this, but then I need to worry about
  54.  * segments.  No thanks.
  55.  */
  56.  
  57. #ifdef M_UNIX
  58. /*
  59.  * I am unsure of these; the i386 contents are not documented in 3.2.2.  I
  60.  * guessed at them by comparing "info regs" with the contents of a jmp_buf
  61.  * immediately after a setjmp().
  62.  */
  63. #define _PC(p) (p->env[5])
  64. #define _SP(p) (p->env[4])
  65. #define _BP(p) (p->env[3])
  66. #endif
  67.  
  68. #ifdef linux
  69. #define _PC(p) (p->env->__pc)
  70. #define _SP(p) (p->env->__sp)
  71. #define _BP(p) (p->env->__bp)
  72. #endif
  73.  
  74. #endif
  75.  
  76. #ifndef UNIX
  77. static int chkintstk __ARGS((void));
  78. #endif
  79. static int stkutil __ARGS((struct proc *pp));
  80.  
  81. void
  82. kinit()
  83. {
  84. #ifndef UNIX
  85.     int i;
  86.  
  87.     /* Initialize interrupt stack for high-water-mark checking */
  88.     for(i=0;i<512;i++)
  89.         Intstk[i] = STACKPAT;
  90.  
  91.     /* Remember location 0 pattern to detect null pointer derefs */
  92.     oldNull = *(unsigned short *)NULL;
  93. #endif
  94. }
  95. /* Print process table info
  96.  * Since things can change while ps is running, the ready proceses are
  97.  * displayed last. This is because an interrupt can make a process ready,
  98.  * but a ready process won't spontaneously become unready. Therefore a
  99.  * process that changes during ps may show up twice, but this is better
  100.  * than not having it showing up at all.
  101.  */
  102. int
  103. ps(argc,argv,p)
  104. int argc;
  105. char *argv[];
  106. void *p;
  107. {
  108.     register struct proc *pp;
  109. #ifndef UNIX
  110.     register struct env *ep;
  111. #endif
  112.     int i;
  113.  
  114. #ifdef UNIX
  115.     tprintf("Uptime %s",tformat(secclock()));
  116. #else
  117.     tprintf("Uptime %s Stack %x max intstk %u psp %04x",tformat(secclock()),
  118.     getss(),chkintstk(),_psp);
  119.     if(Mtasker != 0){
  120.     tprintf("\nRunning under %s",Taskers[Mtasker]);
  121.     }
  122. #endif
  123.     tputs("\n");
  124.  
  125. #ifdef UNIX
  126.     tprintf("PID      SP       stksize  maxstk   event    fl  in  \
  127. out  name\n");
  128.  
  129.     for (pp = Susptab; pp != NULLPROC; pp = pp->next)
  130.     {
  131.         if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d \
  132. %3d  %s\n",
  133.                 FP_SEG(pp), FP_SEG(_SP(pp)), (int32) pp->stksize,
  134.                 (int32) stkutil(pp), FP_SEG(pp->event),
  135.                 pp->i_state ? 'I' : ' ',
  136.                 (pp->state & WAITING) ? 'W' : ' ',
  137.                 (pp->state & SUSPEND) ? 'S' : ' ',
  138.                 pp->input, pp->output, pp->name) == EOF)
  139.             return 0;
  140.     }
  141.     for (i = 0; i < PHASH; i++)
  142.     {
  143.         for (pp = Waittab[i]; pp != NULLPROC; pp = pp->next)
  144.         {
  145.             if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx \
  146. %c%c%c %3d %3d  %s\n",
  147.                     FP_SEG(pp), FP_SEG(_SP(pp)),
  148.                     (int32) pp->stksize, (int32) stkutil(pp),
  149.                     FP_SEG(pp->event),
  150.                     pp->i_state ? 'I' : ' ',
  151.                     (pp->state & WAITING) ? 'W' : ' ',
  152.                     (pp->state & SUSPEND) ? 'S' : ' ',
  153.                     pp->input, pp->output, pp->name) == EOF)
  154.                 return 0;
  155.         }
  156.     }
  157.     for (pp = Rdytab; pp != NULLPROC; pp = pp->next)
  158.     {
  159.         if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx \
  160. %c%c%c %3d %3d  %s\n",
  161.                 FP_SEG(pp), FP_SEG(_SP(pp)), (int32) pp->stksize,
  162.                 (int32) stkutil(pp), FP_SEG(pp->event),
  163.                 pp->i_state ? 'I' : ' ',
  164.                 (pp->state & WAITING) ? 'W' : ' ',
  165.                 (pp->state & SUSPEND) ? 'S' : ' ',
  166.                 pp->input, pp->output, pp->name) == EOF)
  167.             return 0;
  168.     }
  169.     if( Curproc != NULLPROC)
  170.     {
  171.         if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx \
  172. %c%c%c %3d %3d  %s\n",
  173.                 FP_SEG(Curproc), FP_SEG(_SP(Curproc)),
  174.                 (int32) Curproc->stksize, (int32) stkutil(Curproc),
  175.                 FP_SEG(Curproc->event),
  176.                 Curproc->i_state ? 'I' : ' ',
  177.                 (Curproc->state & WAITING) ? 'W' : ' ',
  178.                 (Curproc->state & SUSPEND) ? 'S' : ' ',
  179.                 Curproc->input, Curproc->output,
  180.                 Curproc->name) == EOF)
  181.             return 0;
  182.     }
  183. #else
  184.     tputs("PID  SP        stksize   maxstk    event     fl  in  out  name\n");
  185.  
  186.     for(pp = Susptab;pp != NULLPROC;pp = pp->next){
  187.         ep = (struct env *)&pp->env;
  188.     if(tprintf("%4.4x %-10lx%-10u%-10u%-10lx%c%c%c %3d %3d  %s\n",
  189.      FP_SEG(pp),
  190.          ptol(MK_FP(ep->ss,ep->sp)),
  191.          pp->stksize,
  192.          stkutil(pp),
  193.          ptol(pp->event),
  194.          pp->i_state ? 'I' : ' ',
  195.          (pp->state & WAITING) ? 'W' : ' ',
  196.          (pp->state & SUSPEND) ? 'S' : ' ',
  197.          pp->input, pp->output,
  198.          pp->name) == EOF)
  199.             return 0;
  200.     }
  201.     for(i=0;i<PHASH;i++){
  202.         for(pp = Waittab[i];pp != NULLPROC;pp = pp->next){
  203.             ep = (struct env *)&pp->env;
  204.         if(tprintf("%4.4x %-10lx%-10u%-10u%-10lx%c%c%c %2d %2d  %s\n",
  205.          FP_SEG(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
  206.              ptol(pp->event),
  207.              pp->i_state ? 'I' : ' ',
  208.              (pp->state & WAITING) ? 'W' : ' ',
  209.              (pp->state & SUSPEND) ? 'S' : ' ',
  210.              pp->input,pp->output,
  211.              pp->name) == EOF)
  212.                 return 0;
  213.         }
  214.     }
  215.     for(pp = Rdytab;pp != NULLPROC;pp = pp->next){
  216.         ep = (struct env *)&pp->env;
  217.     if(tprintf("%4.4x %-10lx%-10u%-10u          %c%c%c %2d %2d  %s\n",
  218.      FP_SEG(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
  219.          pp->i_state ? 'I' : ' ',
  220.          (pp->state & WAITING) ? 'W' : ' ',
  221.          (pp->state & SUSPEND) ? 'S' : ' ',
  222.          pp->input,pp->output,
  223.          pp->name) == EOF)
  224.             return 0;
  225.     }
  226.     if(Curproc != NULLPROC){
  227.         ep = (struct env *)&Curproc->env;
  228.     tprintf("%4.4x %-10lx%-10u%-10u          %c   %2d %2d  %s\n",
  229.      FP_SEG(Curproc),ptol(MK_FP(ep->ss,ep->sp)),Curproc->stksize,
  230.          stkutil(Curproc),
  231.          Curproc->i_state ? 'I' : ' ',
  232.          Curproc->input,Curproc->output,
  233.          Curproc->name);
  234.     }
  235. #endif
  236.     return 0;
  237. }
  238. static int
  239. stkutil(pp)
  240. struct proc *pp;
  241. {
  242.     unsigned i;
  243.     register int16 *sp;
  244.  
  245. #ifdef UNIX
  246. #ifdef linux
  247.     if (FP_SEG(pp->stack) == 0xC0000000)
  248. #else
  249.     if (FP_SEG(pp->stack) == 0x80000000)
  250. #endif
  251.         return pp->stksize;
  252. #endif
  253.     i = pp->stksize;
  254.     for(sp = pp->stack;*sp == STACKPAT && sp < pp->stack + pp->stksize;sp++)
  255.         i--;
  256.     return i;
  257. }
  258. /* Return number of used words in interrupt stack. Note hardwired value
  259.  * for stack size; this is also found in the various .asm files
  260.  */
  261. #ifndef UNIX
  262. static int
  263. chkintstk()
  264. {
  265.     register int i;
  266.     register int16 *cp;
  267.  
  268.     for(i=512,cp = Intstk; i != 0 && *cp == STACKPAT; cp++)
  269.         i--;
  270.     return i;
  271. }
  272. #endif
  273.  
  274. /* Verify that stack pointer for current process is within legal limits;
  275.  * also check that no one has dereferenced a null pointer
  276.  */
  277. #ifdef UNIX
  278. static void
  279. #ifdef PROTOTYPES
  280. __chkstk_internal(int16 spp)
  281. #else
  282. __chkstk_internal(spp)
  283.     int16 spp;
  284. #endif
  285. {
  286.     int16 *sp, *sbase, *stop;
  287.  
  288.     sp = &spp;        /* close enough for government work */
  289.     sbase = Curproc->stack;
  290.     if(sbase == NULL)
  291.         return;    /* Main task -- too hard to check */
  292.     stop = sbase + Curproc->stksize;
  293.     if(sp < sbase || sp >= stop){
  294.         tprintf("Stack violation, process %s\n",Curproc->name);
  295.         tprintf("SP = %lx, legal stack range [%lx,%lx)\n",
  296.             ptol(sp),ptol(sbase),ptol(stop));
  297.         tflush();
  298.         rflush();
  299.         killself();
  300.     }
  301. }    
  302. #endif
  303.  
  304. void
  305. chkstk()
  306. {
  307. #ifdef UNIX
  308.     __chkstk_internal(0);    /* must have an argument to take address of */
  309. #else
  310.     int16 *sbase;
  311.     int16 *stop;
  312.     int16 *sp;
  313. #ifdef MULTITASK
  314.     extern int Nokeys;              /* indicates we are shelled out [pc.c]*/
  315. #endif
  316.  
  317.     sp = MK_FP(_SS,_SP);
  318.     if(_SS == _DS){
  319.         /* Probably in interrupt context */
  320.         return;
  321.     }
  322.     sbase = Curproc->stack;
  323.     if(sbase == NULL)
  324.         return; /* Main task -- too hard to check */
  325.  
  326.     stop = sbase + Curproc->stksize;
  327.     if(sp < sbase || sp >= stop){
  328.         printf("Stack violation, process %s\n",Curproc->name);
  329.         printf("SP = %lx, legal stack range [%lx,%lx)\n",
  330.         ptol(sp),ptol(sbase),ptol(stop));
  331.         fflush(stdout);
  332.         killself();
  333.     }
  334.     if(*(unsigned short *)NULL != oldNull){
  335. #ifdef MULTITASK
  336.     if(!Nokeys)     /* don't complain if we are shelled out */
  337. #endif
  338.             printf("WARNING: Location 0 smashed, process %s\n",Curproc->name);
  339.     *(unsigned short *)NULL = oldNull;
  340.         fflush(stdout);
  341.     }
  342. #endif
  343. }
  344. /* Machine-dependent initialization of a task */
  345. void
  346. psetup(pp,iarg,parg1,parg2,pc)
  347. struct proc *pp;        /* Pointer to task structure */
  348. int iarg;               /* Generic integer arg */
  349. void *parg1;            /* Generic pointer arg #1 */
  350. void *parg2;            /* Generic pointer arg #2 */
  351. void (*pc)__ARGS((int,void*,void*));           /* Initial execution address */
  352. {
  353.     register int16 *stktop; /* KF8NH was "int", this breaks 32-bit code */
  354. #ifndef UNIX
  355.     register struct env *ep;
  356. #endif
  357.  
  358.     /* Set up stack to make it appear as if the user's function was called
  359.      * by killself() with the specified arguments. When the user returns,
  360.      * killself() automatically cleans up.
  361.      *
  362.      * First, push args on stack in reverse order, simulating what C
  363.      * does just before it calls a function.
  364.      */
  365.     stktop = (int16 *)(pp->stack + pp->stksize); /* KF8NH as above */
  366. #ifdef UNIX
  367. #ifdef LITTLE_ENDIAN
  368.     *--stktop = (((unsigned long) parg2 & 0xFFFF0000) >> 16) & 0x0000FFFF;
  369.     *--stktop = ((unsigned long) parg2 & 0x0000FFFF);
  370.     *--stktop = (((unsigned long) parg1 & 0xFFFF0000) >> 16) & 0x0000FFFF;
  371.     *--stktop = ((unsigned long) parg1 & 0x0000FFFF);
  372.     *--stktop = (((unsigned long) iarg & 0xFFFF0000) >> 16) & 0x0000FFFF;
  373.     *--stktop = ((unsigned long) iarg & 0x0000FFFF);
  374.     *--stktop = (((unsigned long) killself & 0xFFFF0000) >> 16) & 0x0000FFFF;
  375.     *--stktop = ((unsigned long) killself & 0x0000FFFF);
  376. #else
  377.     *--stktop = ((unsigned long) parg2 & 0x0000FFFF);
  378.     *--stktop = (((unsigned long) parg2 & 0xFFFF0000) >> 16) & 0x0000FFFF;
  379.     *--stktop = ((unsigned long) parg1 & 0x0000FFFF);
  380.     *--stktop = (((unsigned long) parg1 & 0xFFFF0000) >> 16) & 0x0000FFFF;
  381.     *--stktop = ((unsigned long) iarg & 0x0000FFFF);
  382.     *--stktop = (((unsigned long) iarg & 0xFFFF0000) >> 16) & 0x0000FFFF;
  383.     *--stktop = ((unsigned long) killself & 0x0000FFFF);
  384.     *--stktop = (((unsigned long) killself & 0xFFFF0000) >> 16) & 0x0000FFFF;
  385. #endif
  386. #else
  387. #ifdef  LARGEDATA
  388.     *--stktop = FP_SEG(parg2);
  389. #endif
  390.     *--stktop = FP_OFF(parg2);
  391. #ifdef  LARGEDATA
  392.     *--stktop = FP_SEG(parg1);
  393. #endif
  394.     *--stktop = FP_OFF(parg1);
  395.     *--stktop = iarg;
  396.         
  397.     /* Now push the entry address of killself(), simulating the call to
  398.      * the user function.
  399.      */
  400. #ifdef  LARGECODE
  401.     *--stktop = FP_SEG(killself);
  402. #endif
  403.     *--stktop = FP_OFF(killself);
  404. #endif
  405.  
  406.     /* Set up task environment. Note that for Turbo-C, the setjmp
  407.      * sets the interrupt enable flag in the environment so that
  408.      * interrupts will be enabled when the task runs for the first time.
  409.      * Note that this requires newproc() to be called with interrupts
  410.      * enabled!
  411.      */
  412.     setjmp(pp->env);
  413. #ifdef UNIX
  414.     _SP(pp) = stktop;
  415.     _BP(pp) = stktop;
  416.     _PC(pp) = pc;
  417. #else
  418.     ep = (struct env *)&pp->env;
  419.     ep->ss = FP_SEG(stktop);
  420.     ep->sp = FP_OFF(stktop);
  421.     ep->cs = FP_SEG(pc);    /* Doesn't hurt in small model */
  422.     ep->ip = FP_OFF(pc);
  423. #endif
  424.     /* Task initially runs with interrupts on */
  425.     pp->i_state = 1;
  426. }
  427. unsigned
  428. #ifdef PROTOTYPES
  429. phash(volatile void *event)
  430. #else
  431. phash(event)
  432. void *event;
  433. #endif
  434. {
  435.     register unsigned x;
  436.  
  437.     /* Fold the two halves of the pointer */
  438. #ifdef UNIX
  439.     x = (unsigned) event;
  440. #else
  441.     x = FP_SEG(event) ^ FP_OFF(event);
  442. #endif
  443.  
  444.     /* If PHASH is a power of two, this will simply mask off the
  445.      * higher order bits
  446.      */
  447.     return x % PHASH;
  448. }
  449.